1. Technical Field
The present invention relates generally to an improved data processing system and, in particular, to a process and system for dynamically compiling a program.
2. Description of Related Art
Since Java is an interpreted language, any programs written in Java, after being converted into Java class files, are interpreted by a Java virtual machine (JVM). In order to improve performance, many JVMs may compile Java classes into platform-specific binary code after they are loaded into the JVM. Then, instead of being interpreted, Java classes are executed in their compiled native code format, similar to programs written in other languages, such as C, C++, etc. Such just-in-time (JIT) compilation of Java programs can significantly improve the speed of execution of Java programs.
In some early implementations of JIT compilers, JIT compilation is enabled for every method loaded into the JVM for all Java applications. However, the just-in-time compilation time becomes part of the execution time of a Java program. For a given Java class method, JIT compilation can be justified only if the compiled method code executes in less time than the JIT compilation time for the method. Otherwise, the method should be executed by interpreting the method's bytecodes. For typical Java applications, there are many class methods which are only rarely invoked, making JIT compilation of such methods unjustified. As a result, on JVMs with early JIT compilers, loading Java applications with JIT compilation enabled is typically slower than loading the same Java applications with interpretation only (JIT compilation disabled). This is mainly due to the fact that during the Java application loading time, a large number of class methods are invoked relatively few times, making their JIT compilation times unjustified.
In more advanced JVM implementations, JIT compilers compile Java methods selectively, depending on the frequency with which the methods are invoked. This so-called “hot-spot compiling” is a hybrid of interpreting and just-in-time compiling that attempts to combine both techniques in order to yield Java programs that run as fast as natively compiled code. This type of execution may be performed by an interpreter in the execution engine called a “mixed mode interpreter.” A mixed-mode interpreter attempts to analyze or profile the execution of the program in order to determine the locations of the program that justify the time expense for compiling a portion of the program.
The usual approach to optimization is to profile the program to discover exactly where the program spends most of its time and then spend time optimizing portions of the program which execute most often. A Java virtual machine (JVM) that performs hot-spot compiling attempts to optimize only the time-critical portions of a program. In this approach, the JVM begins the execution of the program by interpreting the program. As the JVM interprets the program's bytecodes, it analyzes the execution of the program to determine the program's “hot spots,” which is the part of the program where the program spends most of its time. When it identifies a hot spot, the JVM just-in-time compiles only the portion of the code that encompasses the hot spot.
As the program continues to run, the JVM continues to analyze the program. If another hot spot is revealed, the JVM can just-in-time compile and optimize new areas. Also, the JVM can revert back to using bytecodes for areas that no longer seem time-critical in order to keep the memory footprint at a minimum. Depending upon the host platform, a smaller memory footprint may make the difference between a program fitting or not fitting in memory.
It is important to note that the unit of Java program being JIT compiled or interpreted is whole Java methods. That is, a Java method is either entirely JIT compiled or interpreted in a JVM. Typically, mixed-mode interpreters allow each Java method to be interpreted for a number of times before it is compiled. In one previous solution, each method has an associated invocation counter that is decremented whenever the method is invoked and also when backward branches are encountered. When the counter reaches zero, the associated method is compiled at its next invocation, and subsequent invocations for the method use the compiled code.
A major disadvantage of this solution is that it causes low performance for Java methods with very long running loops. For example, a daemon thread may use an “infinite” or essentially non-terminating loop to handle almost all of its work. Once the daemon thread enters the method, it may never exit. In this extreme but not so uncommon case, the method would be continually interpreted because the daemon thread may never return from the method so that it can be just-in-time compiled (or JITed). As a result, the daemon thread spends all its time in the interpretation mode, even though the method is already determined to be a “hot spot” and is a candidate for JIT compilation.
Therefore, in order to improve the performance of certain Java programs, it would be particularly advantageous to provide a mixed-mode interpreter with the ability to improve the performance of a program with particular types of “hot spots,” such as methods with essentially non-terminating loops.